﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MbUnit.Framework;
using System.Diagnostics;
using System.Reflection;
using Foundation.ObjectHydrator.Tests.POCOs;

namespace Foundation.ObjectHydrator.Tests.HydratorTests
{
    [TestFixture]
    public class Hydrator_SimpleCustomer_Tests
    {
        [Test]
        public void CanGetSingleSimpleCustomer()
        {
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>();
            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(!String.IsNullOrEmpty(customer.Description), "Customer Description should exist.");

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanGetList()
        {
            int listCount = 50;
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>();
            IList<SimpleCustomer> customers = hydrator.GetList(listCount);

            Assert.IsTrue(customers.Count == listCount, "Customer count is wrong.");

            DumpCustomers(customers);
        }

        [Test]
        public void CanGetDescription()
        {
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>();
            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(!String.IsNullOrEmpty(customer.Description), "Customer Description should exist.");

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanConstrainIntegers()
        {
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithInteger("Locations", 5, 10);

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(customer.Locations >= 5 && customer.Locations <= 10, String.Format("Customer Locations [{0}] is outside expected range.", customer.Locations));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanConstrainIntegersWithImproperCasing()
        {
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
            .WithInteger("LoCATIons", 5, 10);

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(customer.Locations >= 5 && customer.Locations <= 10, String.Format("Customer Locations [{0}] is outside expected range.", customer.Locations));

            DumpSimpleCustomer(customer);
        }

        [Test]
        [ExpectedArgumentException]
        public void CatchConstrainIntegersMisspelling()
        {
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
            .WithInteger("Locationsx", 5, 10);
        }

        [Test]
        public void CanDefaultString()
        {
            string defaultValue = "Testing123";

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDefault("Description", defaultValue);

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(defaultValue == customer.Description, String.Format("Default value is not as expected[{0}]", defaultValue));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanGetInteger()
        {
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>();

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(customer.Locations >= 0, String.Format("Customer Locations is expected."));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanGetDouble()
        {
            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>();

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(customer.Revenue >= 0, String.Format("Customer Revenue is expected."));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanConstrainDoubleDecimalPlaces()
        {
            int decimalPlaces = 3;

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDouble("Revenue", decimalPlaces);

            SimpleCustomer customer = hydrator.GetSingle();

            double decimalPart = customer.Revenue - (int)customer.Revenue;
            Assert.IsTrue(decimalPart >= 0, String.Format("Customer Revenue decimal part is expected."));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanConstrainDoubleRange()
        {
            double minimum = 15.76;
            double maximum = 76.43;

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDouble("Revenue", minimum, maximum);

            SimpleCustomer customer = hydrator.GetSingle();


            Assert.Between<double>(customer.Revenue, minimum, maximum);
            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanConstrainDoubleRangeAndDecimals()
        {
            double minimum = 15.76;
            double maximum = 76.43;
            int decimalPlaces = 3;

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDouble("Revenue", minimum, maximum, decimalPlaces);

            SimpleCustomer customer = hydrator.GetSingle();

            double decimalPart = customer.Revenue - (int)customer.Revenue;

            Assert.Between<double>(customer.Revenue, minimum, maximum);
            Assert.IsTrue(decimalPart >= 0, String.Format("Customer Revenue decimal part is expected."));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanDefaultInteger()
        {
            int defaultValue = 73;

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDefault("Locations", defaultValue);

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(defaultValue == customer.Locations, String.Format("Default value is not as expected[{0}]", defaultValue));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanDefaultDateTime()
        {
            DateTime defaultValue = new DateTime(2009, 01, 01);

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDefault("IncorporatedOn", defaultValue);

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(defaultValue == customer.IncorporatedOn, String.Format("Default value is not as expected[{0}]", defaultValue));

            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanChainWithDefaultDescription()
        {
            string defaultValue = "Testing123";
            int minimumValue = 65;
            int maximumValue = 75;

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDefault("Description", defaultValue)
                .WithInteger("Locations", minimumValue, maximumValue);

            SimpleCustomer customer = hydrator.GetSingle();

            Assert.IsTrue(defaultValue == customer.Description, String.Format("Default value is not as expected[{0}]", defaultValue));
            
            Assert.Between<int>(customer.Locations, minimumValue, maximumValue, String.Format("Customer Locations [{0}] is outside expected range [{1},{2}].", customer.Locations, minimumValue, maximumValue));
            DumpSimpleCustomer(customer);
        }

        [Test]
        public void CanConstrainDates()
        {
            DateTime minimumValue = new DateTime(2009, 01, 01);
            DateTime maximumValue = new DateTime(2009, 01, 10);

            Hydrator<SimpleCustomer> hydrator = new Hydrator<SimpleCustomer>()
                .WithDate("IncorporatedOn", minimumValue, maximumValue);

            SimpleCustomer customer = hydrator.GetSingle();

            
            Assert.Between<DateTime>(customer.IncorporatedOn, minimumValue, maximumValue, String.Format("Customer IncorporatedOn [{0}] is outside expected range [{1}, {2}].", customer.IncorporatedOn, minimumValue, maximumValue));
            DumpSimpleCustomer(customer);

        }

        private void DumpCustomers(IList<SimpleCustomer> customers)
        {
            foreach (SimpleCustomer customer in customers)
            {
                DumpSimpleCustomer(customer);
            }
        }
        private void DumpSimpleCustomer(Object theObject)
        {
            Trace.WriteLine("");
            foreach (PropertyInfo propertyInfo in theObject.GetType().GetProperties())
            {
                Trace.WriteLine(String.Format("{0} [{1}]", propertyInfo.Name, propertyInfo.GetValue(theObject, null)));
            }

        }
     
    }

  
}
